/*
 * Copyright (C) 2011 Project R'yleh Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.Arkham;

import java.util.ArrayList;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.content.res.Configuration;
import android.graphics.BitmapFactory;
import android.graphics.Color;
import android.media.MediaPlayer;
import android.os.Bundle;
import android.os.Handler;
import android.util.Log;
import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.view.Window;
import android.view.ViewGroup.LayoutParams;
import android.widget.TextView;
import android.widget.Toast;

public class Battle extends Activity implements OnClickListener
{
	ViewCore mGL;
	final static String TAG = "Battle";
	final static int VOCABGAME = 100;
	final static int MATHGAME = 200;
	final static int TARGETING = 300;
	static boolean ATTACKED = false;
	static boolean MOVED = false;
	static boolean CONTINUE = true;
	static boolean WON = false;
	private boolean toggleMenu = false;
	private boolean subAct = false;
	Timer battleTime;
	float Xpos, Ypos, Zpos;
	MediaPlayer bgMusic, winSound, loseSound, physicalSound, magicSound;
	String LogMessage;
	
	private int TargetXpos = 0; //the targets Xpos
	private int TargetYpos = 0; //the targets Ypos
	private Handler handle;
	
	//menu buttons
	View btnMenu, btnMove, btnAttack, btnMagic, btnEndTurn, btnTarget, btnExit;
	
	public void onCreate(Bundle savedInstanceState)
	{
		super.onCreate(savedInstanceState);
		//removes title bar and sets the theme
		this.requestWindowFeature(Window.FEATURE_NO_TITLE); 
		mGL = new ViewCore(this);
		setContentView(mGL);
		LayoutInflater inflater = (LayoutInflater)getSystemService(Context.LAYOUT_INFLATER_SERVICE);
		
		handle = new Handler();
		
		//grabs mainmenu.xml to use as display layout
		ViewGroup ViewMain = (ViewGroup) inflater.inflate(com.Arkham.R.layout.battle, null);
		
		this.addContentView(ViewMain, new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));
		TextView tv = (TextView) findViewById(com.Arkham.R.id.BattleText);
		mGL.renderer.setmTextView(tv);
		battleTime = new Timer();
		mGL.renderer.setTimer(battleTime);
		
		
		
		View RotateLeft = findViewById(com.Arkham.R.id.RotateCameraLeft);
		RotateLeft.setOnClickListener(this);
		View RotateRight = findViewById(com.Arkham.R.id.RotateCameraRight);
		RotateRight.setOnClickListener(this);
		  
		//menu buttons
		btnMenu = findViewById(com.Arkham.R.id.btnMenu);
		btnMenu.setOnClickListener(this);
		btnMove = findViewById(com.Arkham.R.id.btnMove);
		btnMove.setOnClickListener(this);
		btnAttack = findViewById(com.Arkham.R.id.btnAttack);
		btnAttack.setOnClickListener(this);
		btnMagic = findViewById(com.Arkham.R.id.btnMagic);
		btnMagic.setOnClickListener(this);
		btnEndTurn = findViewById(com.Arkham.R.id.btnEndTurn);
		btnEndTurn.setOnClickListener(this);
		btnTarget = findViewById(com.Arkham.R.id.btnTarget);
		btnTarget.setOnClickListener(this);
		btnExit = findViewById(com.Arkham.R.id.btnExit);
		btnExit.setOnClickListener(this);
		btnExit.setVisibility(View.INVISIBLE);
		  
		mGL.renderer.mView = btnMagic;
		  
		
		//Music
		bgMusic = MediaPlayer.create(this, R.raw.battle_march_long);	//Set background music
		bgMusic.setLooping(true);										//Set bgMusic to loop
		if(bgMusic != null)
			bgMusic.start();												//Plays the music
		winSound = MediaPlayer.create(this, R.raw.level_up);		//Set sound effect for winning
		loseSound = MediaPlayer.create(this, R.raw.death_music);	//Set sound effect for loseing
		physicalSound = MediaPlayer.create(this, R.raw.physical_attack);		//Set sound effect for winning
		magicSound = MediaPlayer.create(this, R.raw.physical_attack);	//Set sound effect for loseing
				
		CONTINUE = true;
		initBattleScene();
		//battleLoop();
	  }
	
	public void onClick(View v) 
	  {
		  
		  switch (v.getId())
		  {
	    	case com.Arkham.R.id.RotateCameraLeft:
	    	{
	    		mGL.renderer.decreaseOrbit();
	    		for(int i = 1; i < mGL.renderer.root.size(); i++)
	    		{
	    			mGL.renderer.root.get(i).updateRotation(0.0f, -60.f, 0.0f);
	    			mGL.renderer.root.get(i).mShouldLoadTexture = true;
	    			
	    		}
	    		break;
	    	}
	    	case com.Arkham.R.id.RotateCameraRight:
	    	{
	    		mGL.renderer.increaseOrbit();
	    		for(int i = 1; i < mGL.renderer.root.size(); i++)
	    		{
	    			mGL.renderer.root.get(i).updateRotation(0.0f, 60.f, 0.0f);
	    			mGL.renderer.root.get(i).mShouldLoadTexture = true;
	    		}
	    		break;
	    	}
	    	case com.Arkham.R.id.btnMenu:
	    	{
	    		if(toggleMenu){
	    			btnMove.setVisibility(View.INVISIBLE);
		    		btnAttack.setVisibility(View.INVISIBLE);
		    		btnMagic.setVisibility(View.INVISIBLE);
	    			btnEndTurn.setVisibility(View.INVISIBLE);
	    			btnTarget.setVisibility(View.INVISIBLE);
	    			
		    		toggleMenu = !toggleMenu;
	    		}
	    		else{
	    			if(!MOVED)
	    				btnMove.setVisibility(View.VISIBLE);
	    			if(!ATTACKED){
		    			btnAttack.setVisibility(View.VISIBLE);
	    				btnMagic.setVisibility(View.VISIBLE);
	    			}
	    			btnTarget.setVisibility(View.VISIBLE);
		    		btnEndTurn.setVisibility(View.VISIBLE);
		    		toggleMenu = !toggleMenu;
	    		}
	    		
	    		break;
	    	}
	    	case com.Arkham.R.id.btnMove:
	    	{
	    		if(BattleInfo.playerTarget.character.getName() == 
	    			new BattleCharacter().character.getName()){
	    			Toast.makeText(this, "No target destination selected.", Toast.LENGTH_SHORT).show();
	    		}
	    		else{
	    			move();
	    		}
	    		break;
	    	}
	    	case com.Arkham.R.id.btnAttack:
	    	{
	    		physicalAttack();
	    		break;
	    	}
	    	case com.Arkham.R.id.btnMagic:
	    	{
	    		magicAttack();
	    		break;
	    	}
	    	case com.Arkham.R.id.btnTarget:
	    	{
	    		subAct = true;
	    		startActivityForResult(new Intent(this, Targeting.class), TARGETING);
	    		break;
	    	}
	    	case com.Arkham.R.id.btnEndTurn:
	    	{
	    		endTurn();
	    		break;
	    	}
	    	case com.Arkham.R.id.btnExit:
	    	{
	    		finish();
	    		break;
	    	}
		  }
		  
	  }

	
	@Override
	public void onActivityResult(int requestCode, int resultCode, Intent data){
		super.onActivityResult(requestCode, resultCode, data);
		if(requestCode == VOCABGAME){
			subAct = false;
			Bundle bundle = data.getExtras();
			int time = (int)bundle.getLong("TIME"); //The time to answer the question
			boolean answer = bundle.getBoolean("ANS");  //If you got the answer right or wrong
			//Attack Character
			if(BattleInfo.physicalAttack(BattleInfo.playerTarget, time, answer))
			{
				mGL.renderer.root.remove(BattleInfo.playerTarget.character.getSprite());
			}
			physicalSound.start();
			ATTACKED = true;
			Toast.makeText(this, BattleInfo.ToastText, Toast.LENGTH_SHORT).show();
		}
		if(requestCode == MATHGAME){
			subAct = false;
			Bundle bundle = data.getExtras();
			int time = (int)bundle.getLong("TIME"); //The time to answer the question
			boolean answer = bundle.getBoolean("ANS");  //If you got the answer right or wrong
			//Attack Character
			BattleInfo.magicalAttack(BattleInfo.playerTarget, time, answer);
			magicSound.start();
			ATTACKED = true;
			Toast.makeText(this, BattleInfo.ToastText, Toast.LENGTH_SHORT).show();
		}
		if(requestCode == TARGETING){
			subAct = false;
			Toast.makeText(this, BattleInfo.playerTarget.character.getName() + " is your target", Toast.LENGTH_LONG).show();
		}
	}
	
	private void initBattleScene()
	{
		//Initializing Battle Information
		BattleInfo.deployCharacters();
		ATTACKED = false;
		MOVED = false;
		
		Square LevelMap = new Square(15,15);
		LevelMap.loadBitmap(BitmapFactory.decodeResource(this.getResources(),R.drawable.uvtemplate001lg ));
		LevelMap.setRotation(90.0f, 0.0f, 0.0f);
		LevelMap.setTranslation(0, -1, 0);
		mGL.renderer.addMesh(LevelMap);

		
//		Actor testSprite = new Actor(1,1, BitmapFactory.decodeResource(getResources(), com.Arkham.R.drawable.testchar), 64,64);
//		Actor testSprite = new Actor(1,1, BitmapFactory.decodeResource(getResources(), com.Arkham.R.drawable.testchar3), 128,128);
//		GameFile.party.characters[0].setActor(testSprite);
//		GameFile.party.characters[0].getSprite().setTranslation(0.0f, 0.0f, 0.0f);
//		GameFile.party.characters[0].getSprite().setClickable(true);
		
//		mGL.renderer.addMesh(GameFile.party.characters[0].getSprite());
//		mGL.renderer.setFocus(GameFile.party.characters[0].getSprite().mTranslate);


		String POSITION;
		//Actor testSprite;
		for(int i=0; i<BattleInfo.Good.size(); i++){
//			Actor testSprite = new Actor(1,1, BitmapFactory.decodeResource(getResources(), com.Arkham.R.drawable.testchar), 64,64);
			Xpos = BattleInfo.Good.get(i).Xpos - BattleInfo.BoardXVariance;
			Ypos = 0.0f;
			Zpos = BattleInfo.Good.get(i).Ypos - BattleInfo.BoardYVariance;
			POSITION = "Good " + i + ": " + BattleInfo.Good.get(i).character.getName() + 
			           " pos(X: " + Xpos + ", " +
			           " Y: " + Ypos + ", " +
			           " Z: " + Zpos + ")";
			BattleInfo.Good.get(i).character.getSprite().setTranslation(Xpos, Ypos, Zpos);
			BattleInfo.Good.get(i).character.getSprite().setClickable(true);
			mGL.renderer.addMesh(BattleInfo.Good.get(i).character.getSprite());
			BattleInfo.Good.get(i).character.getSprite().indexID = mGL.renderer.getListSize() - 1;
			Log.i("Dispatch Log", POSITION);
		}
		
		for(int i=0; i<BattleInfo.Bad.size(); i++){
			Xpos = BattleInfo.Bad.get(i).Xpos - BattleInfo.BoardXVariance;
			Ypos = 0;
			Zpos = BattleInfo.Bad.get(i).Ypos - BattleInfo.BoardYVariance;
			POSITION = "Bad " + i + ": " + BattleInfo.Bad.get(i).character.getName() + 
	           " pos(X: " + Xpos + ", " +
	           " Y: " + Ypos + ", " +
	           " Z: " + Zpos + ")";
			BattleInfo.Bad.get(i).character.getSprite().setTranslation(Xpos, Ypos, Zpos);
			BattleInfo.Bad.get(i).character.getSprite().setClickable(true);
			BattleInfo.Bad.get(i).character.getSprite().indexID = mGL.renderer.getListSize() - 1;
			mGL.renderer.addMesh(BattleInfo.Bad.get(i).character.getSprite());
			Log.i("Dispatch Log", POSITION);
		}
//		mGL.renderer.setFocus(BattleInfo.Bad.get(2).character.getSprite().mTranslate);
//	    mGL.renderer.activeIndex; //currently or last selected index.
//		Toast.makeText(this, "Magus ID is " + BattleInfo.Good.get(0).character.getSprite().indexID, Toast.LENGTH_LONG)
//		.show();
		
		//call endTurn to start battle
		endTurn();
	}

	@Override
	protected void onResume(){
		super.onResume();
		for(int i =0; i < mGL.renderer.root.size(); i++)
		mGL.renderer.root.get(i).mShouldLoadTexture = true;
	}
	
	@Override
	protected void onPause()	//When sub-activity is called or the user hits the back button
	{
		if(!subAct){
			if(bgMusic != null)
				bgMusic.stop();
		}
		super.onPause();												
	}
	
	@Override
	protected void onStop(){
		super.onStop();
	}
	
	@Override
	protected void onRestart(){
		super.onRestart();
	}
	
	public void onConfigurationChanged(Configuration newConfig) { 
		super.onConfigurationChanged(newConfig); 
	}
	
	
	private void magicAttack(){
		//All characters are considered to have reach 3 as base
		int range = 3;
		int Xpos = BattleInfo.nextToAct.Xpos;
		int Ypos = BattleInfo.nextToAct.Ypos;
		
		//create targeting layout and set to BattleInfo.BattleMap[Constants.ATTACKABILITY]
		BattleInfo.attackability(Xpos, Ypos, range);
		
		if(BattleInfo.AttackableMagical.contains(BattleInfo.playerTarget)){
			//Call Math Mini Game Sub Function
			subAct = true;
			startActivityForResult(new Intent(this, MathGame.class), MATHGAME);
    		btnAttack.setVisibility(View.INVISIBLE);
    		btnMagic.setVisibility(View.INVISIBLE);
    		ATTACKED = true;
    		//finish attack in onActivityResult()
		}else{
			Toast.makeText(this, BattleInfo.playerTarget.character.getName() + " not in range", Toast.LENGTH_SHORT).show();
		}
	}
	
	private void physicalAttack(){
		//All characters are considered to have reach 1 as base
		int range = 1;
		int Xpos = BattleInfo.nextToAct.Xpos;
		int Ypos = BattleInfo.nextToAct.Ypos;
		
		//create targeting layout and set to BattleInfo.BattleMap[Constants.ATTACKABILITY]
		BattleInfo.attackability(Xpos, Ypos, range);
		
		if(BattleInfo.AttackablePhysical.contains(BattleInfo.playerTarget)){
			//Call Vocab Mini Game Sub Function
			subAct = true;
			startActivityForResult(new Intent(this, VocabGame.class), VOCABGAME);
    		btnAttack.setVisibility(View.INVISIBLE);
    		btnMagic.setVisibility(View.INVISIBLE);
    		ATTACKED = true;
    		//finish attack in onActivityResult()
		}else{
			Toast.makeText(this, BattleInfo.playerTarget.character.getName() + " not in range", Toast.LENGTH_SHORT).show();
		}
	}
	
	private void move(){
		BattleInfo.AImoveToward(BattleInfo.playerTarget);
		btnMove.setVisibility(View.INVISIBLE);
		MOVED = true;
		Xpos = BattleInfo.nextToAct.Xpos - BattleInfo.BoardXVariance;
		Ypos = 0.0f;
		Zpos = BattleInfo.nextToAct.Ypos - BattleInfo.BoardYVariance;
		BattleInfo.nextToAct.character.getSprite().setTranslation(Xpos, Ypos, Zpos);
		BattleInfo.calculateAttackables();
		//find the path to follow and set it to BattleInfo.path
//		ArrayList<String> course = new ArrayList<String>();
//		BattleInfo.findPath(Xpos, Ypos, goalXpos, goalYpos, speed, course);
		//use BattleInfo.path to move character on map
		MOVED = true;
	}
	
	private void endTurn(){
		btnMove.setVisibility(View.INVISIBLE);
		btnAttack.setVisibility(View.INVISIBLE);
		btnMagic.setVisibility(View.INVISIBLE);
		btnEndTurn.setVisibility(View.INVISIBLE);
		btnMenu.setVisibility(View.INVISIBLE);
		btnTarget.setVisibility(View.INVISIBLE);
		toggleMenu = false;
		ATTACKED = false;
		MOVED = false;
		checkForEndState();
		if(CONTINUE){
		   BattleInfo.getNextActor();
		   TimerLogi();
		   while( BattleInfo.Bad.contains(BattleInfo.nextToAct)&& CONTINUE ){
		     runAI();
		     checkForEndState();
		     BattleInfo.getNextActor();
		     TimerLogi();
		   }
		}
		if(CONTINUE){
		   btnMenu.setVisibility(View.VISIBLE);
		   btnMove.setVisibility(View.VISIBLE);
    	   btnAttack.setVisibility(View.VISIBLE);
		   btnMagic.setVisibility(View.VISIBLE);
		   btnTarget.setVisibility(View.VISIBLE);
    	   btnEndTurn.setVisibility(View.VISIBLE);
    	   Toast.makeText(this, "It is " + BattleInfo.nextToAct.character.getName() +"'s turn.", Toast.LENGTH_SHORT).show();
		}
		else
			battleEND();
	}
	
	private void TimerLogi(){
		   LogMessage = BattleInfo.nextToAct.character.getName() + " is next to act\n";
			for(int i=0; i<BattleInfo.Good.size(); i++){
				LogMessage += BattleInfo.Good.get(i).character.getName();
				LogMessage += "'s Timer is: " + BattleInfo.Good.get(i).timer;
				LogMessage += " & HP: " +  BattleInfo.Good.get(i).character.getEquippedStats().getCurrentHealth();
				LogMessage += "/" + BattleInfo.Good.get(i).character.getEquippedStats().getMaxHealth();
				LogMessage += " Speed: " + BattleInfo.Good.get(i).speed +"\n";
			}
			for(int i=0; i<BattleInfo.Bad.size(); i++){
				LogMessage += BattleInfo.Bad.get(i).character.getName();
				LogMessage += "'s Timer is: " + BattleInfo.Bad.get(i).timer;
				LogMessage += " & HP: " +  BattleInfo.Bad.get(i).character.getEquippedStats().getCurrentHealth();
				LogMessage += "/" + BattleInfo.Bad.get(i).character.getEquippedStats().getMaxHealth();
				LogMessage += " Speed: " + BattleInfo.Bad.get(i).speed +"\n";
			}
		   Log.i("Battle Log", LogMessage);
	}
	
	private void runAI(){
		//runs the AI
		Toast.makeText(this, "It is " + BattleInfo.nextToAct.character.getName() +"'s turn.", Toast.LENGTH_SHORT).show();
		BattleInfo.AI();
		Toast.makeText(this, BattleInfo.ToastText, Toast.LENGTH_SHORT).show();
		
		Xpos = BattleInfo.nextToAct.Xpos - BattleInfo.BoardXVariance;
		Ypos = 0.0f;
		Zpos = BattleInfo.nextToAct.Ypos - BattleInfo.BoardYVariance;
		BattleInfo.nextToAct.character.getSprite().setTranslation(Xpos, Ypos, Zpos);
	}
	
	private void checkForEndState(){
			if( BattleInfo.Good.isEmpty() ){
				CONTINUE = false;
				WON = false;
			}
			else if( BattleInfo.Bad.isEmpty() ){
				CONTINUE = false;
				WON = true;	
			}
	}
	
	private void battleEND(){
		bgMusic.stop();
		if(WON){
			
			GameFile.storyFlag[1] = true;

			//add George to party
			if( GameFile.party.characters[1].getName() == "" ){
			        int newItemLocation;
			        GameFile.party.characters[1].changeName("George");
			        GameFile.party.characters[1].changeWorstFear("Homonyms");
			         GameFile.party.inventory.gainItem(Armory.Pencil());
			        newItemLocation = GameFile.party.inventory.size() - 1;
			        GameFile.party.equip(newItemLocation, Constants.R_HAND, GameFile.party.characters[1]);
			         GameFile.party.inventory.gainItem(Armory.Eraser());
			         newItemLocation = GameFile.party.inventory.size() - 1;
			        GameFile.party.equip(newItemLocation, Constants.L_HAND, GameFile.party.characters[1]);
			         GameFile.party.inventory.gainItem(Armory.SchoolUniform());
			        newItemLocation = GameFile.party.inventory.size() - 1;
			        GameFile.party.equip(newItemLocation, Constants.BODY, GameFile.party.characters[1]);
			         GameFile.party.inventory.gainItem(Armory.UniformShoes());
			         newItemLocation = GameFile.party.inventory.size() - 1;
			        GameFile.party.equip(newItemLocation, Constants.FEET, GameFile.party.characters[1]);      
			 }
			
			
			int p=0;
			while( GameFile.party.characters[p].getName() != "" ){
			    int HP = GameFile.party.characters[p].getEquippedStats().getMaxHealth();
			    GameFile.party.characters[p].getEquippedStats().setCurrentHealth(HP);	//heal
			    GameFile.party.inventory.gainMoney( 25 * GameFile.party.characters[p].getLevel() );	//give moneys
			    GameFile.party.characters[p].gainALevel();	//level up!
			    p++;
			}
			
			Toast.makeText(this, "You WIN!!! Congratulations", Toast.LENGTH_LONG).show();
			Toast.makeText(this, "George joins your party!", Toast.LENGTH_LONG).show();
			Toast.makeText(this, "The court yard is now open for random battles.", Toast.LENGTH_LONG).show();
			if(winSound != null)
				winSound.start();
		}
		//if lost battle
		else{
			int p=0;
			while( GameFile.party.characters[p].getName() != "" ){
			   int HP = GameFile.party.characters[p].getEquippedStats().getMaxHealth();
			   GameFile.party.characters[p].getEquippedStats().setCurrentHealth(HP);  //heal
			   p++;
			}
			
			
			Toast.makeText(this, "You Lose!!! The Dark One binds and imprisons you.. for all of eternity.", Toast.LENGTH_LONG).show();
			if(loseSound != null)
				loseSound.start();
		}
		btnExit.setVisibility(View.VISIBLE);
	}
}